/*
File:		Projectile.cpp
Author:		Ben Feldmann
Purpose:	Class to manage game projectiles
*/

#include "Projectile.h"
#include "Animation.h"
#include "EventSystem.h"
#include "MessageSystem.h"
#include "DestroyEntityMessage.h"
#include "GamePlayState.h"
#include "Game.h"
#include "BaseGun.h"
#include "Tile.h"
#include "Game.h"
#include "GamePlayState.h"
#include "Player.h"
#include "Level.h"
#include "Room.h"
#include "CreateProjectileMessage.h"
#include "SGD Wrappers\CSGD_XAudio2.h"


Animation* fire = new Animation;
Projectile::Projectile()
{
	//fire->LoadAnimationFromFile("FireAnimation.xml");
	//fire->Play(true);

	type = OBJ_BULLET;

	owner = nullptr;

	trail = nullptr;

	explosionID = EmitterManager::GetInstance()->CreateEmitterTemplate(Emitter::LoadEmitter("Emitters/enemydeath.xml"));

	explosion = EmitterManager::GetInstance()->CreateEmitterFromTemplate(explosionID);
	explosion->SetEmissionRate(20);

	fireLife = 0;
	lifeTimer = 0;

	//SetDirection(owner->GetDirection());


	//ObjectManager::GetInstance()->AddObject(this);
}

Projectile::~Projectile()
{

}

void Projectile::Update(float elapsed) 
{
	//Bug Fix #62 Start - Brandon Jones
	if(bulletType == RW_FLAME)
	{
		lifeTimer += elapsed;

		if(lifeTimer >= fireLife)
		{
			DestroyEntityMessage* msg = new DestroyEntityMessage(this);
			MessageSystem::GetInstance()->SendMsg(msg);
			msg = nullptr;
			return;
		}
	}
	//Bug Fix #62 End

	switch(GetDirection())
	{
	case 0:	// Right
		SetX(GetX() + GetMoveSpeed()*elapsed);
		if(trail != nullptr)
		{
			trail->SetPosition(GetX()+5,GetY()+(GetHeight()/2.0f));
			trail->Update(elapsed);
		}
		break;

	case 1:	// Left
		SetX(GetX() - GetMoveSpeed()*elapsed);
		if(trail != nullptr)
		{
			trail->SetPosition(GetX()+20,GetY()+(GetHeight()/2.0f));
			trail->Update(elapsed);
		}
		break;

	case 2:	// Down
		SetY(GetY() + GetMoveSpeed()*elapsed);
		if(trail != nullptr)
		{
			trail->SetPosition(GetX()+12,GetY()-10);
			trail->Update(elapsed);
		}
		break;

	case 3:	// Up
		SetY(GetY() - GetMoveSpeed()*elapsed);
		if(trail != nullptr)
		{
			trail->SetPosition(GetX()+12,GetY()+10);
			trail->Update(elapsed);
		}
		break;
		/*case 1:
		SetY(GetY() - GetMoveSpeed()*elapsed);
		break;

		case 2:
		SetX(GetX() + .5f*(GetMoveSpeed()*elapsed));
		SetY(GetY() - .5f*(GetMoveSpeed()*elapsed));
		break;

		case 3:
		SetX(GetX() + GetMoveSpeed()*elapsed);
		break;

		case 4:
		SetX(GetX() + .5f*(GetMoveSpeed()*elapsed));
		SetY(GetY() + .5f*(GetMoveSpeed()*elapsed));
		break;

		case 5:
		SetY(GetY() + GetMoveSpeed()*elapsed);
		break;

		case 6:
		SetX(GetX() - .5f*(GetMoveSpeed()*elapsed));
		SetY(GetY() + .5f*(GetMoveSpeed()*elapsed));
		break;

		case 7:
		SetX(GetX() - GetMoveSpeed()*elapsed);
		break;


		case 8:
		SetX(GetX() - .5f*(GetMoveSpeed()*elapsed));
		SetY(GetY() - .5f*(GetMoveSpeed()*elapsed));
		break;*/
	}


	//fire->Update(elapsed);

	int width = Game::GetInstance()->GetScreenWidth();
	int height = Game::GetInstance()->GetScreenHeight();

	int camX = GamePlayState::GetInstance()->GetCamX();
	int camY = GamePlayState::GetInstance()->GetCamY();

	if(GetX() + GetWidth() > camX + width)
	{
		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;
	}
	else if(GetX() < camX)
	{
		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;
	}
	else if(GetY() + GetHeight() > camY + height)
	{
		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;
	}	
	else if(GetY() < camY)
	{
		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;
	}

}

void Projectile::Render() 
{
	if(trail != nullptr)
		trail->Render();

	float rotation;

	switch(GetDirection())
	{
	case 0:
		rotation = 0;
		break;

	case 1:
		rotation = (SGD_PI);
		break;

	case 2:
		rotation = (SGD_PI)/2;
		break;

	case 3:
		rotation = (3*SGD_PI)/2;
		break;
	}
	if(GetTextureID() != -1)
	{
		CSGD_TextureManager::GetInstance()->Draw(GetTextureID(),
			int(GetX()- GamePlayState::GetInstance()->GetCamX()),
			int(GetY() - GamePlayState::GetInstance()->GetCamY()),
			bulletType == RW_ROCKET ? 1.5f : 1.0f, bulletType == RW_ROCKET ? 1.5f : 1.0f, nullptr,
			(float)GetWidth()/2, (float)GetHeight()/2, bulletType == RW_FLAME ? 0 : rotation);
	}
}

bool Projectile::CheckCollision(IEntity* base) 
{
	if(Entity::CheckCollision(base) == true && base != this->GetOwner())
	{
		if( base->GetType() == OBJ_HAZARD )
		{
			//if(this->GetBulletType() != RW_ROCKET && this->GetBulletType() != MISSLE_BARRAGE)
			EventSystem::GetInstance()->SendEvent("target_hit", base, new float(this->damage));
		}

		if((ownerType == OBJ_PLAYER && base->GetType() == OBJ_ENEMY))
		{
			//if(this->GetBulletType() != RW_ROCKET && this->GetBulletType() != MISSLE_BARRAGE)
			EventSystem::GetInstance()->SendEvent("target_hit", base, new float(this->damage));

			if(this->GetBulletType() == RW_EMP)
				dynamic_cast<Enemy*>(base)->SetStunTime(1.0f);
			else if(this->GetBulletType() == RW_FLAME)
				dynamic_cast<Enemy*>(base)->SetSlow(1.0f, 0.25f);
		}

		if(ownerType == OBJ_ENEMY && base->GetType() == OBJ_PLAYER)
		{
			EventSystem::GetInstance()->SendEvent("player_hit", base, new float(this->damage),
				new int(dynamic_cast<Player*>(base)->GetPlayerNum()));
		}

		if(base->GetType() == OBJ_TILE && dynamic_cast<Tile*>(base)->GetTileType() != TILE_COLLISION)
		{
			return false;
		}

		if(base->GetType() == OBJ_BULLET || base->GetType() == OBJ_WEAPON || base->GetType() == OBJ_PICKUP ||
			base->GetType() == ownerType)
			return false;

		if(this->GetBulletType() == RW_ROCKET || this->GetBulletType() == MISSLE_BARRAGE)
			Explosion();

		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;

		return true;
	}

	return false;
}

void Projectile::SetOwner(Entity* o)
{
	if( owner )
		owner->Release();

	if(o)
		owner = o;
	else
		return;

	if( owner )
		owner->AddRef();

	if(this->GetOwner()->GetType() == OBJ_WEAPON)
		ownerType = OBJ_PLAYER;
	else
		ownerType = OBJ_ENEMY;
}

void Projectile::Explosion()
{
	explosion->SetPosition(GetX()+(GetWidth()/2.0f), GetY()+(GetHeight()/2.0f));
	EmitterManager::GetInstance()->FireBurstEmitter(explosion);

	GamePlayState* self = GamePlayState::GetInstance();

	CSGD_XAudio2::GetInstance()->SFXPlaySound(self->GetExplodeSoundID());

	if(self->GetPlayer()->GetRoomNum() >= 0)
	{
		vector<Enemy*> enemyList = self->GetLevel()->GetRoom(self->GetPlayer()->GetRoomNum())->GetEnemyVec();
	
		for(unsigned int i = 0; i < enemyList.size(); ++i)
		{
			int xdist = (int)(enemyList[i]->GetX() - GetX());
			int ydist = (int)(enemyList[i]->GetY() - GetY());
			if( sqrt((float)xdist*xdist + (float)ydist*ydist) < 128 )
				EventSystem::GetInstance()->SendEvent("target_hit", enemyList[i], new float(this->damage/4));
		}
	}
}